package com.project.taohaoCoupons.merchant.admin.service.basics.chain;

import org.springframework.beans.BeansException;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.*;

@Component
public final class MerchantAdminChainContext<T> implements ApplicationContextAware, CommandLineRunner {
    /**
     * 应用上下文， Spring IOC 获取 Bean 实例
     */
    private ApplicationContext context;

    private final Map<String, List<MerchantAdminAbstractChainHandler>> CHAINMAP = new HashMap<>();

    /**
     *  根据 mark 标识从责任链容器中获取一组责任链实现 Bean 集合
     * @param mark
     * @param requestPram
     */
    public  void  handle(String mark,T requestPram)  {
        List<MerchantAdminAbstractChainHandler> handlerList = CHAINMAP.get(mark);
        if (CollectionUtils.isEmpty(handlerList)) {
            throw new RuntimeException(String.format("[%s] Chain of Responsibility ID is undefined.", mark));
        }
        for (MerchantAdminAbstractChainHandler handler : handlerList) {
            handler.handler(requestPram);
        }
    }

    /**
     *  从 Spring IOC 容器中获取指定接口 Spring Bean 集合
     * @param args
     * @throws Exception
     */
    @Override
    public void run(String... args) throws Exception {
        Map<String,MerchantAdminAbstractChainHandler> map=context.getBeansOfType(MerchantAdminAbstractChainHandler.class);
        map.forEach( (beanName,bean)->{
            // 根据mark标记一组责任链集合
            List<MerchantAdminAbstractChainHandler> abstractChainHandlers = CHAINMAP.getOrDefault(bean.mark(), new ArrayList<>());
            abstractChainHandlers.add(bean);
            CHAINMAP.put(bean.mark(), abstractChainHandlers);
        });
        CHAINMAP.forEach((mark,list)->{
            // 对责任链集合进行排序,通过其继承的Ordered接口来得到顺序
            list.sort(Comparator.comparing(MerchantAdminAbstractChainHandler::getOrder));
        });
    }

    /**
     * 注入Spring应用上下文
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }
}
